package com.gopay.checkorder.service.task;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.time.StopWatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.checkorder.dao.BisBankOrderQueryDAO;
import com.gopay.checkorder.service.BankOrderService;
import com.gopay.checkorder.service.alarm.OrderAlarmDataCollector;
import com.gopay.checkorder.service.alarm.OrderAlarmRecordStorage;
import com.gopay.checkorder.service.task.thread.CheckOrderTaskThread;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.bank.BankOrderStatus;
import com.gopay.common.constants.bank.BankOrderType;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.domain.bank.BankOrder;
import com.gopay.common.domain.cps.vo.CheckOrderResult;
import com.gopay.common.util.DateUtils;

public class CmbB2bCheckOrderTaskImpl implements Task {

    private final static Logger logger = LoggerFactory.getLogger("CHECK_ORDER");

    private final static int MAX_SIZE = 10000;

    @Resource(name = "bisBankOrderQueryDAO")
    private BisBankOrderQueryDAO bisBankOrderQueryDAO;

    @Resource(name = "checkOrderTaskThread")
    private CheckOrderTaskThread checkOrderTaskThread;

    @Resource(name = "orderAlarmRecordStorage")
    private OrderAlarmRecordStorage orderAlarmRecordStorage;

    @Resource(name = "bankOrderService")
    private BankOrderService bankOrderService;

    private void printLog(StopWatch sw, String prefix) {
        sw.split();
        logger.error(prefix + "------,耗时=" + sw.getSplitTime());
    }

    @Override
    public void doTask() {
        try {
            StopWatch sw = new StopWatch();
            sw.start();
            printLog(sw, "cmbB2BCheckOrderJob------start");

            int pageSize = 100;
            int count = 0;

            Date date = new Date();
            int resCount = getCheckOrderCount(date);
            printLog(sw, "cmbB2BCheckOrderJob------对单总数量=" + resCount);
            // 订单对账报警采集者
            OrderAlarmDataCollector alarmCollector = new OrderAlarmDataCollector();
            List<BankOrder> list = null;
            while (count < resCount) {
                list = getCheckOrder(date, 1, pageSize);
                if (list == null || list.size() == 0) {
                    printLog(sw, "cmbB2BCheckOrderJob------分页为空，跳出while循环");
                    break;
                }
                printLog(sw, "cmbB2BCheckOrderJob------list.size()=" + list.size() + ",count=" + count);

                for (BankOrder bankOrder : list) {

                    alarmCollector.addTotal(bankOrder.getBankCode());

                    CheckOrderResult checkResult = bankOrderService.checkOrder(bankOrder,
                            BankOrderStatus.AUTO_CHECK_SUCCESS);
                    if (checkResult != null && checkResult.isCommunicateError() == true) {
                        logger.error("checkResult  communicateError-----------" + checkResult.isCommunicateError());
                        alarmCollector.addFail(bankOrder.getBankCode());
                        logger.error("checkResult  fail*****" + alarmCollector.getFail(bankOrder.getBankCode()));
                        logger.error("checkResult  total****" + alarmCollector.getTotal(bankOrder.getBankCode()));
                    }
                    sleep(2000);

                }
                count += pageSize;
            }
            // 判断报警阈值并保存报警记录
            orderAlarmRecordStorage.store(alarmCollector);
            
            printLog(sw, "cmbB2BCheckOrderJob------结束while循环,resCount=" + resCount);

            printLog(sw, "cmbB2BCheckOrderJob------end");
            sw.stop();

        } catch (Throwable t) {
            logger.error("执行对单Task时出现异常", t);
        }

    }

    private void sleep(long pausesTime) {
        try {
            Thread.sleep(pausesTime);
        } catch (InterruptedException e) {
            logger.error(getClass().getName() + " CMB doTask fail.", e);
        }
    }
    
    /**
     * 待对账订单笔数
     * 
     * @param orderStatus
     * @param totalCheckTimes
     * @return
     */
    protected int getCheckOrderCount(Date date) {
        Map<String, Object> params = new HashMap<String, Object>();
        StringBuffer hql = new StringBuffer("select count(*) ");
        hql.append(buildHqlAndParamsOfCmbB2B(params));

        int resCount = bisBankOrderQueryDAO.findCountByHql(hql.toString(), params);
        if (resCount > MAX_SIZE) {
            resCount = MAX_SIZE;
        }
        return resCount;
    }

    private String buildHqlAndParamsOfCmbB2B(Map<String, Object> params) {
        StringBuffer hql = new StringBuffer("");
        hql.append(" from BankOrder ");
        hql.append(" where orderStatus in (:orderStatus00,:orderStatus92)  ");
        hql.append(" and bankBizProdCode = :bankBizProdCode  ");
        hql.append(" and orderType = :orderType ");
        hql.append(" and bankCode = :bankCode ");
        hql.append(" and sendBankTm >to_date(:beginTime,'yyyyMMddHH24miss') ");

        // map
        params.put("orderStatus00", BankOrderStatus.PROCESS);
        params.put("orderStatus92", BankOrderStatus.VERIFY_FAIL);
        // params.put("orderStatus96", BankOrderStatus.ENTER_ACCOUNT_FIAL);
        params.put("bankBizProdCode", BisBankBusinessProd._01.value);
        params.put("orderType", BankOrderType.GOPAY_BIS_ORDER);
        params.put("bankCode", BankConstants.BANK_LOGO_CMB);

        // 开始时间--最近20天
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DAY_OF_MONTH, -20);
        params.put("beginTime", DateUtils.format(calendar.getTime(), "yyyyMMddHHmmss"));

        return hql.toString();
    }

    /**
     * 分页查询对账记录
     * 
     * @param orderStatus
     * @param totalCheckTimes
     * @param pageIndex
     * @param pageSize
     * @return
     */
    protected List<BankOrder> getCheckOrder(Date date, int pageIndex, int pageSize) {
        Map<String, Object> params = new HashMap<String, Object>();

        StringBuilder sb = new StringBuilder();
        sb.append(buildHqlAndParamsOfCmbB2B(params));
        sb.append(" order by totalCheckTimes asc ");

        return bisBankOrderQueryDAO.findByHql(sb.toString(), params, pageIndex, pageSize);
    }

}
